package db.queries;

import java.util.Collection;

import core.exceptions.DBAccessException;
import core.objects.Author;
import core.objects.Book;
import core.objects.Category;
import core.objects.ObjectWithID;
import core.objects.Publisher;
import db.ICrossInsert;
import db.dbTables.AbstractDBTable;
import db.dbTables.AuthorTable;
import db.dbTables.BookTable;
import db.dbTables.CategoryTable;
import db.dbTables.DbColumn;
import db.dbTables.PublisherTable;
import db.queries.core.BaseObjectQueriesInfo;
import db.queries.core.QueriesEnvironment;

public class BookQueries extends BaseObjectQueriesInfo<Book> {

	private final static int QUERY_TYPE_BOOK = 0;
	private final static int QUERY_TYPE_CROSS_AUTHOR = 1;
	private final static int QUERY_TYPE_CROSS_CATEGORY = 2;
	private final static int QUERY_TYPE_CROSS_PUBLISHER = 3;
	
	private int queryType = QUERY_TYPE_BOOK;
	private boolean selectObj = false;
	
	@Override
	protected AbstractDBTable getTable() {
		switch (queryType) {
			case QUERY_TYPE_BOOK:
				return QueriesEnvironment.getBookTable();
			case QUERY_TYPE_CROSS_AUTHOR:
				return QueriesEnvironment.getBookCrossAuthorTable();
			case QUERY_TYPE_CROSS_CATEGORY:
				return QueriesEnvironment.getBookCrossCategoryTable();
			case QUERY_TYPE_CROSS_PUBLISHER:
				return QueriesEnvironment.getBookCrossPublisherTable();
			default:
				return null;
		}
	}
	
	@Override
	protected DBAccessException foreignKeyConstrainstViolation(String key, Throwable e) {
		if (key.equals(BookTable.COLUMN_ID)) {
			return new DBAccessException("Error: Unknown book", e);
		} else if (key.equals(CategoryTable.COLUMN_ID)) {
			return new DBAccessException("Error: No such Category to add to book", e);
		} else if (key.equals(AuthorTable.COLUMN_ID)) {
			return new DBAccessException("Error: No such Author to add to book", e);
		} else if (key.equals(PublisherTable.COLUMN_ID)) {
			return new DBAccessException("Error: No such Publisher to add to book", e);
		} else {
			return new DBAccessException("Unknown error has occured", e);
		}
	}
	
	@Override
	protected DbColumn getIDColumn() {
		switch (queryType) {
			case QUERY_TYPE_BOOK:
				return QueriesEnvironment.getBookTable().id;
			case QUERY_TYPE_CROSS_AUTHOR:
				if (selectObj) {
					return QueriesEnvironment.getBookCrossAuthorTable().authorId;
				}
				return QueriesEnvironment.getBookCrossAuthorTable().bookId;
			case QUERY_TYPE_CROSS_CATEGORY:
				if (selectObj) {
					return QueriesEnvironment.getBookCrossCategoryTable().categroyId;
				}
				return QueriesEnvironment.getBookCrossCategoryTable().bookId;
			case QUERY_TYPE_CROSS_PUBLISHER:
				if (selectObj) {
					return QueriesEnvironment.getBookCrossPublisherTable().publisherId;
				}
				return QueriesEnvironment.getBookCrossPublisherTable().bookId;
			default:
				return null;
		}
	}

	@Override
	protected DbColumn getNameColumn() {
		switch (queryType) {
		case QUERY_TYPE_BOOK:
			return QueriesEnvironment.getBookTable().name;
		case QUERY_TYPE_CROSS_AUTHOR:
			return QueriesEnvironment.getAuthorTable().name;
		case QUERY_TYPE_CROSS_CATEGORY:
			return QueriesEnvironment.getCategoryTable().name;
		case QUERY_TYPE_CROSS_PUBLISHER:
			return QueriesEnvironment.getPublisherTable().name;
		default:
			return null;
	}
	}

	@Override
	protected void determineTable(ObjectWithID obj, boolean selectObj) {
		this.selectObj = selectObj;
		if (obj instanceof Author) {
			queryType = QUERY_TYPE_CROSS_AUTHOR;
		} else if (obj instanceof Category) {
			queryType = QUERY_TYPE_CROSS_CATEGORY;
		} else if (obj instanceof Publisher) {
			queryType = QUERY_TYPE_CROSS_PUBLISHER;
		} else {
			queryType = QUERY_TYPE_BOOK;
		}
	}

	@Override
	protected DbColumn getAbsoluteIDColumn() {
		return QueriesEnvironment.getBookTable().id;
	}

	@Override
	protected ICrossInsert getCross() {
		return new ICrossInsert() {
			
			@Override
			public Collection<? extends ObjectWithID> getCrossObjects(ObjectWithID obj) {
				switch (queryType) {
					case QUERY_TYPE_CROSS_AUTHOR:
						return ((Book)obj).getAuthors();
					case QUERY_TYPE_CROSS_CATEGORY:
						return ((Book)obj).getCategories();
					case QUERY_TYPE_CROSS_PUBLISHER:
						return ((Book)obj).getPublishers();
					default:
						return null;
				}
			}
		};
	}	

}
